import 'dart:io';

import 'package:convergence_media/features/api/apis/circle_csavs_api.dart';
import 'package:convergence_media/features/app/repository/app_config_repository.dart';
import 'package:convergence_media/features/config/errors/login_errors.dart';
import 'package:convergence_media/features/config/logger/logger.dart';
import 'package:convergence_media/features/user/repositories/token_repository.dart';
import 'package:dio/dio.dart';

/// {@template post_interceptor}
/// 圈子的网络请求拦截器
/// {@endtemplate}
class CircleInterceptor extends QueuedInterceptor {
  /// {@macro post_interceptor}
  CircleInterceptor({
    required CircleCsavsApi circleCsavsApi,
    required Dio circleDio,
    required AppConfigRepository appConfigRepository,
    required TokenRepository tokenRepository,
  })  : _circleCsavsApi = circleCsavsApi,
        _circleDio = circleDio,
        _appConfigRepository = appConfigRepository,
        _tokenRepository = tokenRepository;

  final TokenRepository _tokenRepository;
  final AppConfigRepository _appConfigRepository;
  final Dio _circleDio;
  final CircleCsavsApi _circleCsavsApi;

  @override
  Future<void> onRequest(
    RequestOptions options,
    RequestInterceptorHandler handler,
  ) async {
    logger.t('messCircleInterceptorage.onRequest: ${options.uri}');
    if (options.path.startsWith('/login/tokenLogin')) {
      return handler.next(options);
    }
    if (options.headers['token'] == null) {
      // 由导航拦截器处理，确保空安全
      final currentHashId = _appConfigRepository.getCurrentHashId()!;

      final token = await _tokenRepository.getCircleToken(currentHashId);
      if (token != null) {
        /// 存在 token 装载并继续
        options.headers['token'] = token;
        // 继续请求
        return handler.next(options);
      } else {
        /// 重新在后端获取 Token

        // 由导航拦截器处理，确保空安全
        final mainToken = await _tokenRepository.getMainToken(currentHashId);

        // 登录并获取 token
        final loginTokenLoginResponse =
            await _circleCsavsApi.postLoginTokenLogin(mainToken!);

        // 拿出 token
        final newCircleToken = loginTokenLoginResponse.data.loginToken;
        // 缓存 token
        await _tokenRepository.putCircleToken(currentHashId, newCircleToken);
        // 重新设置请求头
        options.headers['token'] = newCircleToken;
        return handler.resolve(Response(requestOptions: options));
      }
    } else {
      super.onRequest(options, handler);
    }
  }

  @override
  Future<void> onError(
    DioException err,
    ErrorInterceptorHandler handler,
  ) async {
    if (err.response?.statusCode == HttpStatus.unauthorized) {
      // 尝试主 token 刷新后重试
      final currentHashId = _appConfigRepository.getCurrentHashId();
      if (currentHashId == null) {
        return handler.reject(
          DioException(
            requestOptions: err.requestOptions,
            message: AuthException.withoutToken().toString(),
          ),
        );
      }
      final mainToken = await _tokenRepository.getMainToken(currentHashId);
      if (mainToken == null) {
        return handler.reject(
          DioException(
            requestOptions: err.requestOptions,
            message: AuthException.withoutToken().toString(),
          ),
        );
      }

      final circleCsavsApi = CircleCsavsApi(dio: _circleDio);
      try {
        final loginResponse =
            await _circleCsavsApi.postLoginTokenLogin(mainToken);

        final i = await _tokenRepository.putCircleToken(
          currentHashId,
          loginResponse.data.loginToken,
        );
        // handler.resolve();
      } on AuthException catch (e) {
        logger.e(e);
      } catch (e) {
        logger.e(e);
      }
    }
    super.onError(err, handler);
  }
}
